<?php

/*
 * Module for sending email notifications on certain events.
 */

// Get the config values from the module.
include_once('config.inc.php');
include_once('foxyback.class.inc.php');
include_once('includes/class.phpmailer.php');
include_once('includes/class.smtp.php');

class Notify {

	// Set class variables;
	var $error_info = '';

	// Constructor.	
	function __construct() {
	}

	// Send a non-error email message to the ERROR_ADDRESS.
	function sendMessageEmail ($output, $subject=NULL) { 
		global $ERROR_ADDRESS;

		if ($subject == '') {
			$subject = "FoxyBack Message";
		}
		$body = "The following occurred on " . date('Y-m-d H:i:s') . "\n$output";

		// Use the custom mail function. Ignore an error, which would be bad at this point.
		$this->sendEmail($subject, $body, '', $ERROR_ADDRESS);

		return 1;
	}

	// Send an email message to the ERROR_ADDRESS.
	function sendErrorEmail ($output) {
		global $ERROR_ADDRESS;

		$subject = "FoxyBack error!";
		$body = "The following error occurred on " . date('Y-m-d H:i:s') . "\n$output";

		// Use the custom mail function. Ignore an error, which would be bad at this point.
		$this->sendEmail($subject, $body, '', $ERROR_ADDRESS);

		return 1;
	}

	// Send an email message to the customer based on a status change.
	function sendStatusMessage ($transaction_id, $status_id) {
		global $modx, $EMAIL_TEMPLATE_ON_STATUS;

		// Display debugging info.
		$debug = false;

		if (!is_array($EMAIL_TEMPLATE_ON_STATUS) || !$status_id || !$transaction_id) {
			$this->error_info = 'Missing parameter in sendStatusMessage';
			return NULL;
		}

		$foxyback = new FoxyBack();

		// Look up the name of this status.
		$status_name = '';
		$status_array = $foxyback->getStatusList();
		foreach ($status_array as $status) {
			if ($status['status_id'] == $status_id) {
				$status_name = $status['name'];
			}
		}
		if ($debug) print "Got status $status_name for id $status_id\n";

		if ($status_name == '') {
			$this->error_info = 'Invalid status in sendStatusMessage';
			return NULL;
		}

		$template_id = $EMAIL_TEMPLATE_ON_STATUS[$status_name];
		if ($template_id <= 0) {
			// No template defined for this status.
			if ($debug) print "no template for this status!!\n";
			return 1;
		}
		if ($debug) print "Got template id: $template_id\n";

		// Get the customer's email address.
		$transaction_view = $foxyback->getTransactionView($transaction_id);
		$customer_id = $transaction_view['customer_id'];
		$customer_view = $foxyback->getCustomerView($customer_id);
		$customer_email = $customer_view['email'];

		// View the address
		$address_view = $foxyback->getAddressView($customer_view['address_id']);

		// Deal with specific statuses.
		if ($status_name == 'Shipped') {
			// Since we are using AtLastFulfillment (inside hook.class.inc.php), 
			// do not send the shipping notification message unless a tracking number has been assigned.
			if ($transaction_view['ship_tracking_number'] <= 0) {
				if ($debug) print "no tracking number yet, so message will not be sent\n";
				return 1;
			}
		}

		// Get the document content.
		$document_array = $modx->getDocument($template_id);
		$content = $document_array['content'];
		
		// The document title is the subject.
		$subject = $document_array['pagetitle'];

		//if ($debug) print "Document: \n".print_r($content, true).print "\n\n";

		// Prepare placeholder substitutions for most messages.
		$placeholders = array(
			'transaction_id' 			=> $transaction_id,
			'customer_id' 				=> $customer_id,
			'transaction_datetime' 		=> $transaction_view['transaction_date'],
			'current_date' 				=> date('Y-m-d'),
			'notes' 					=> $transaction_view['notes'],
			'order_status_id' 			=> $transaction_view['order_status_id'],
			'order_status' 				=> $status_name,
			'ship_tracking_number' 		=> $transaction_view['ship_tracking_number'],
			'tracking_number' 			=> $transaction_view['ship_tracking_number'],
			'ship_reference_number' 	=> $transaction_view['ship_reference_number'],
			'ship_datetime' 			=> $transaction_view['ship_date'],
			'ship_method' 				=> $transaction_view['ship_method'],
			'rma_number' 				=> $transaction_view['rma_number'],
			'first_name'				=> $address_view['first_name'],
			'last_name'					=> $address_view['last_name'],
			'email'						=> $customer_view['email'],
		);

		if ($placeholders['ship_datetime'] == '') {
			// Use the current date.
			$placeholders['ship_datetime'] = date('Y-m-d');
		}

		// Split up the date fields for more flexibility.
		list($placeholders['transaction_date'], $placeholders['transaction_time']) 
			= explode(" ", $transaction_view['transaction_date']);

		list($placeholders['ship_date'], $placeholders['ship_time']) 
			= explode(" ", $placeholders['ship_datetime']);

		if ($status_name == 'Shipped') {
			// Ensure certain placeholders are never empty.
			if ($placeholders['ship_method'] == '') {
				// List all of the shipping addresses to find the carrier.
				$address_list = $foxyback->getAddressList($customer_id, $transaction_id, 'SHIPPING');

				// The carrier is stored as the 'service description'.
				// Loop until a service description is found.
				foreach ($address_list as $address) {
					if ($address['service_description'] != '') {
						$placeholders['ship_method'] = $address['service_description'];
						break;
					}
				}
			}
		}

		// Perform the placeholder substitutions.
		foreach ($placeholders as $key => $value) {
			$content = preg_replace("/\[\+$key\+\]/m", $value, $content);
			$subject = preg_replace("/\[\+$key\+\]/m", $value, $subject);
		}

		if ($debug) print "Subject line: $subject\n";
		$body = '';
		$body_html = '';

		/*
		 * Parse the document to build the body and html body of the message. 
		 * This can work two ways:
		 *	1) If there's an <html> tag, that section will be used for an html message,
		 *		and anything inside <text_version> will be used for the text message.
		 *	2) The entire content is treated as a text message
		 */	
		if (preg_match("/<html>/mi", $content)) {
			if ($debug) print "HTML message\n";
			// HTML.
			// Pull out the text version if it exists.
			if (preg_match("/<text_version>(.*)<\/text_version>/mis", $content, $matches)) {
				if ($debug) print "Got text message\n";
				$body = $matches[1];

				// Remove the text version so the remaining document can be used for the html version.
				$content = preg_replace("/<text_version>.*<\/text_version>/mis", "", $content);
			}
			$body_html = $content;
		}
		else {
			// Just plain text.
			if ($debug) print "Just plain text\n";
			$body = $content;
		}

		if ($debug) print "Body: $body\n\nHTML: $body_html\n\n";

		// Send the message.
		$email_id = $this->sendEmail($subject, $body, $body_html, $customer_email, '', $transaction_id);
		if (!$email_id) {
			// $this contains the error already.
			return NULL;
		}

		return 1;
	}
	// end of sendStatusMessage

	// Prepare a message and send it.
	function sendEmail ($subject, $body, $body_html='', $to_address, $to_name='', $transaction_id='') {

		// Use values from the config file.
		global $modx, $FROM_ADDRESS, $FROM_ADDRESS_NAME, $SMTP_USERNAME, $SMTP_PASSWORD, $FORWARD_TO_ADDRESS, $TEST_MODE_ADDRESS;

		// Display debugging information on standard out.
		$debug = false;

		// Use the PHPMailer class.
		$mailer = new PHPMailer();

		// Send to the "test mode" address if one is defined.
		if (isset($TEST_MODE_ADDRESS) && $TEST_MODE_ADDRESS != '') {
			$to_address = $TEST_MODE_ADDRESS;
		}
		
		if ($debug) print "From: $FROM_ADDRESS To: $to_address\n";

		// Set the from address.
		$mailer->From = $FROM_ADDRESS;
		$mailer->FromName = $FROM_ADDRESS_NAME;
		$mailer->Sender = $FROM_ADDRESS;

		// Use SMTP.
		$mailer->IsSMTP();
		$mailer->SMTPAuth = true;
		$mailer->Username = $SMTP_USERNAME;
		$mailer->Password = $SMTP_PASSWORD;
		$mailer->SMTPDebug = false;

		// Set the to address.
		$mailer->AddAddress($to_address, $to_name);

		// Forward a copy of this message if requested.
		if ($FORWARD_TO_ADDRESS != '' && $FORWARD_TO_ADDRESS != $to_address) {
			$mailer->AddBCC($FORWARD_TO_ADDRESS);
		}
		
		// INSERT A TEST ADDRESS FOR INITIAL AUDITING!
		// REMOVE THIS LATER!!!!!!!!
		if ($to_address != $ERROR_ADDRESS) {
			$mailer->AddBCC($ERROR_ADDRESS);
		}
		if ($to_address != $FORWARD_TO_ADDRESS) {
			$mailer->AddBCC($FORWARD_TO_ADDRESS);
		}

		// Set the subject.
		$mailer->Subject = $subject;

		// Set the body based on whether a body html exists or not.
		$mailer->Body = $body;

		if ($body_html != '') {
			$mailer->Body = $body_html;
			// Indicate that the body is html.
			$mailer->IsHTML(true);

			// Set the text-only body.
			$mailer->AltBody = $body;
		}

		if ($debug) print "<br>\n" . print_r($mailer) . print "<br>\n";

		// Archive this message.
		$archive_spec = array(
			'transaction_id' 	=> $modx->db->escape($transaction_id),
			'from_address' 		=> $modx->db->escape($FROM_ADDRESS),
			'to_address' 		=> $modx->db->escape($to_address),
			'subject' 			=> $modx->db->escape($subject),
			'body' 				=> $modx->db->escape($body),
			'body_html' 		=> $modx->db->escape($body_html),
			'add_date' 			=> $modx->db->escape(date('Y-m-d H:i:s')),
		);

		$email_archive_id = $modx->db->insert($archive_spec, $modx->getFullTableName('foxyback_email_archive'));

		// Send the message.	
		if (!$mailer->Send()) {
			// ERROR!
			$error = "Got error sending email: ";
			$error .= $mailer->ErrorInfo;
			$this->error_info = $error;

			// Save the error to the archived message.
			$edit_spec = array(
				'error' => $modx->db->escape($error),
			);
			$edit_id = $modx->db->update($edit_spec, $modx->getFullTableName('foxyback_email_archive'), "email_archive_id = '$email_archive_id'");

			return NULL;
		}
		if ($debug) print "Send was successful\n</pre>\n";

		return 1;
	}
	// end of sendEmail

}
// end of Notify class
?>
